﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TSON.GeoCOM
{
    public enum TMC_INCLINE_PRG
    {
        TMC_MEA_INC = 0, // Use sensor (apriori sigma)
        TMC_AUTO_INC = 1, // Automatic mode (sensor/plane)
        TMC_PLANE_INC = 2, // Use plane (apriori sigma)
    };
    public enum TMC_MEASURE_PRG
    {
        TMC_STOP = 0, // Stop measurement program
        TMC_DEF_DIST = 1, // Default DIST-measurement program
        TMC_CLEAR = 3, // TMC_STOP and clear data
        TMC_SIGNAL = 4, // Signal measurement (test function)
        TMC_DO_MEASURE = 6, // (Re)start measurement task
        TMC_RTRK_DIST = 8, // Distance-TRK measurement program
        TMC_RED_TRK_DIST = 10, // Reflectorless tracking
        TMC_FREQUENCY = 11 // Frequency measurement (test)
    };
    enum TMC_FACE_DEF
    {
        TMC_FACE_NORMAL, // Face in normal position
        TMC_FACE_TURN // Face turned
    };
    public class TMC
    {
        #region MEASUREMENT FUNCTIONS
        public static RC GetCoordinate(TsSerialPort com, int waitTime, TMC_INCLINE_PRG mode, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2082:{0},{1}\r\n", waitTime, mode));
            responseString = responseString.Trim();
            //E[double],N[double],H[double],CoordTime[long],E-Cont[double],N-Cont[double],H-Cont[double],CoordContTime[long]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC GetSimpleMea(TsSerialPort com, int waitTime, TMC_INCLINE_PRG mode, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2108:{0},{1}\r\n", waitTime, mode));
            responseString = responseString.Trim();
            //Hz[double],V[double],SlopeDistance[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC GetAngle1(TsSerialPort com, TMC_INCLINE_PRG mode, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2003:{0}\r\n", mode));
            responseString = responseString.Trim();
            //Hz[double],V[double],AngleAccuracy[double],AngleTime[long],CrossIncline[double],LengthIncline[double], AccuracyIncline[double],InclineTime[long],FaceDef[long]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC GetAngle(TsSerialPort com, TMC_INCLINE_PRG mode, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2107:{0}\r\n", mode));
            responseString = responseString.Trim();
            //Hz[double],V[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC QuickDist(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2117:\r\n"));
            responseString = responseString.Trim();
            //dHz[double],dV[double],dSlopeDistance[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC GetFullMeas(TsSerialPort com,int waitTime,TMC_INCLINE_PRG mode, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2167:{0},{1}\r\n", waitTime, mode));
            responseString = responseString.Trim();
            //Hz[double],V[double],AccAngle[double],C[double],L[double],AccIncl[double],SlopeDist[double],DistTime[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        #endregion

        #region MEASUREMENT CONTROL FUNCTIONS
        public static RC DoMeasure(TsSerialPort com, TMC_MEASURE_PRG command, TMC_INCLINE_PRG mode)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2008:{0},{1}\r\n", command, mode));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC SetHandDist(TsSerialPort com, double slopeDistance, double hgtOffset, TMC_INCLINE_PRG mode)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2019:{0},{1},{2}\r\n",
                slopeDistance.ToString(), hgtOffset.ToString(), mode));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        #endregion

        #region DATA SETUP FUNCTIONS
        /// <summary>
        /// returning the current reflector height
        /// </summary>
        public static RC GetHeight(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2011:\r\n"));
            responseString = responseString.Trim();
            //Height[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        /// <summary>
        /// GeoCOM原版函数名有歧义，故写了两个相同的函数
        /// </summary>
        public static RC GetReflectorHeight(TsSerialPort com, ref string outString)
        {
            return GetHeight(com, ref outString);
        }
        /// <summary>
        /// setting a new reflector height
        /// </summary>
        public static RC SetHeight(TsSerialPort com, double height)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2012:{0}\r\n", height.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        /// <summary>
        /// GeoCOM原版函数名有歧义，故写了两个相同的函数
        /// </summary>
        public static RC SetReflectorHeight(TsSerialPort com, double height)
        {
            return SetHeight(com, height);
        }
        public static RC GetAtmCorr(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2029:\r\n"));
            responseString = responseString.Trim();
            //Lambda[double],Pressure[double], DryTemperature[double],WetTemperature[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC SetAtmCorr(TsSerialPort com, double lambda,double pressure, double dryTemperature,double wetTemperature)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2028:{0},{1},{2},{3}\r\n",
                lambda.ToString(), pressure.ToString(), dryTemperature.ToString(), wetTemperature.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC SetOrientation(TsSerialPort com, double hzOrientation)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2113:{0}\r\n", hzOrientation.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC GetPrismCorr(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2023:\r\n"));
            responseString = responseString.Trim();
            //PrismCorr[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC GetRefractiveCorr(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2031:\r\n"));
            responseString = responseString.Trim();
            //RefOn[boolean],EarthRadius[double], RefractiveScale[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC SetRefractiveCorr(TsSerialPort com, bool refOn,double earthRadius, double refractiveScale)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2030:{0},{1},{2}\r\n",
                Convert.ToInt32(refOn).ToString(), earthRadius.ToString(), refractiveScale.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        
        /// <summary>
        /// setting the refraction model
        /// </summary>
        /// <param name="com">TsSerialPort</param>
        /// <param name="method">Refraction data:
        /// Method = 1 means method 1 (for the rest of the world)
        /// Method = 2 means method 2 (for Australia)</param>
        /// <returns></returns>
        public static RC SetRefractiveMethod(TsSerialPort com, int method)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2090:{0}\r\n",
                method.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC GetStation(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2009:\r\n"));
            responseString = responseString.Trim();
            //E0[double],N0[double],H0[double],Hi[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC SetStation(TsSerialPort com, double e0, double n0, double h0, double hi)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2010:{0},{1},{2},{3}\r\n",
                e0.ToString(), n0.ToString(), h0.ToString(), hi.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC GetAtmPpm(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2151:\r\n"));
            responseString = responseString.Trim();
            //dPpmA[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC SetAtmPpm(TsSerialPort com, double dPpmA)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2148:{0}\r\n",
                dPpmA.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC GetGeoPpm(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2154:\r\n"));
            responseString = responseString.Trim();
            //unGeomUseAutomatic[unsigned short],dScaleFactorCentralMeridian[double],dOffsetCentralMeridian[double],dHeightReductionPPM[double],dIndividualPPM[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC SetGeoPpm(TsSerialPort com, int unGeomUseAutomatic, double dScaleFactorCentralMeridian, double dOffsetCentralMeridian, double dHeightReductionPPM, double dIndividualPPM)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2153:{0},{1},{2},{3},{4}\r\n",
                unGeomUseAutomatic.ToString(), dScaleFactorCentralMeridian.ToString(),
                dOffsetCentralMeridian.ToString(), dHeightReductionPPM.ToString(),
                dIndividualPPM.ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        #endregion

        #region INFORMATION FUNCTIONS
        public static RC GetFace(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2026:\r\n"));
            responseString = responseString.Trim();
            //Face[long] 使用时可以转换成TMC_FACE_DEF
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        /// <summary>
        /// GeoCOM原版函数名有歧义，故写了两个相同的函数
        /// </summary>
        public static RC GetFacePosition(TsSerialPort com, ref string outString)
        {
            return GetFace(com, ref outString);
        }
        public static RC GetSignal(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2022:\r\n"));
            responseString = responseString.Trim();
            //SignalIntensity[double],Time[long]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        /// <summary>
        /// GeoCOM原版函数名有歧义，故写了两个相同的函数
        /// </summary>
        public static RC GetEDMSignalintensity(TsSerialPort com, ref string outString)
        {
            return GetSignal(com, ref outString);
        }
        #endregion
        
        #region CONFIGURATION FUNCTIONS
        public static RC GetAngSwitch(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2014:\r\n"));
            responseString = responseString.Trim();
            //InclineCorr[long],StandAxisCorr[long],CollimationCorr[long],TiltAxisCorr[long]
            //返回的4个值每一个都是ON_OFF_TYPE
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC GetInclineSwitch(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2007:\r\n"));
            responseString = responseString.Trim();
            //SwCorr[long]  ON_OFF_TYPE
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC SetInclineSwitch(TsSerialPort com, ON_OFF_TYPE swCorr)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2006:{0}\r\n",
                Convert.ToInt32(swCorr).ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        
        public static RC SetEdmMode(TsSerialPort com, EDM_MODE mode)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2020:{0}\r\n",
                Convert.ToInt32(mode).ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC GetSimpleCoord(TsSerialPort com,int waitTime,TMC_INCLINE_PRG eProg, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2116:{0},{1}\r\n", 
                waitTime.ToString(), Convert.ToInt32(eProg).ToString()));
            responseString = responseString.Trim();
            //dCoordE[double], dCoordN[double], dCoordH[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC IfDataAzeCorrError(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2114:\r\n"));
            responseString = responseString.Trim();
            //bAtrCorrectionError[long]
            //Flag, if ATR correction error occurred or not
            //FALSE: no error occurred
            //TRUE: last data record not corrected with the ATR deviation
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC IfDataIncCorrError(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2115:\r\n"));
            responseString = responseString.Trim();
            //bIncCorrectionError[long]
            //Flag, if incline correction error occurred or not
            //FALSE: no error occurred
            //TRUE: last data record not corrected with the incline-correction
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        public static RC SetAngSwitch(TsSerialPort com, ON_OFF_TYPE inclineCorr, ON_OFF_TYPE standAxisCorr,
            ON_OFF_TYPE collimationCorr, ON_OFF_TYPE tiltAxisCorr)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2016:{0},{1},{2},{3}\r\n",
                Convert.ToInt32(inclineCorr).ToString(), Convert.ToInt32(standAxisCorr).ToString(),
                Convert.ToInt32(collimationCorr).ToString(), Convert.ToInt32(tiltAxisCorr).ToString()));
            responseString = responseString.Trim();
            return Helpers.getRcCode(responseString);
        }
        public static RC GetSlopeDistCorr(TsSerialPort com, ref string outString)
        {
            string responseString = com.getResponse(string.Format("\n%R1Q,2126:\r\n"));
            responseString = responseString.Trim();
            //dPpmCorr[double], dPrismCorr[double]
            outString = Helpers.getInfoString(responseString);
            return Helpers.getRcCode(responseString);
        }
        #endregion

    }
}
